package com.jweb.plugins.mybatis.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;

import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jweb.framework.InstanceFactory;
import com.jweb.framework.db.TransactionProxy;
import com.jweb.plugins.mybatis.MybatisPlugin;

/**
 * MybatisMapper动态代理 使用的jdk动态代理。
 * 
 * @author Yuan
 */
public class AopMybatisMapper<T> implements InvocationHandler {
	private Class<?> targetClass;
	private Logger log = LoggerFactory.getLogger(getClass());

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public T init(Class<?> targetObject) {
		this.targetClass = targetObject;
		ClassLoader classLoader = targetObject.getClassLoader();
		Class[] interfaces = new Class[] { targetObject };
		return (T) Proxy.newProxyInstance(classLoader, interfaces, this);
	}

	/**
	 * 动态代理 执行类<br/>
	 * 不要捕获异常，要主动往调用方抛出异常。<br/>
	 * 记2015-10-21 22:17:02 被自己坑。。
	 */
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object ret = null;
		Connection conn = null;
		try {
			conn = InstanceFactory.getDataSourceFactory().getConnection();
			SqlSession sqlSession = MybatisPlugin.getSqlSessionFactory().openSession(conn);
			log.info("[dao] " + targetClass.getSimpleName() + "." + method.getName());
			Object dao = sqlSession.getMapper(targetClass);
			ret = method.invoke(dao, args);
		} finally {
			// 如果没有开启事物，主动关闭连接；否则让事物代理去关闭
			if (!TransactionProxy.flagContainer.get()) {
				// sqlSession.close();//这里不能关，事务已交给aop管理，这样好么？
				conn.commit();
				conn.close();
			}
		}
		return ret;
	}
}